package org.easier.framework.redis.spring.impl;


import org.easier.framework.redis.RedisAdapter;
import org.easier.framework.json.JsonAgent;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis缓存客户端
 * 使用前需初始化 redisTemplate  并且给CacheAgent 指定实现类
 */

public class SpringRedisTemplate implements RedisAdapter {

    private RedisTemplate<String, String> redisTemplate;


    @Override
    public String get(String key) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        String result = valueOperation.get(key);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        return result;
    }

    @Override
    public <T> T get(String key, Class<T> clazz) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        String result = valueOperation.get(key);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        return JsonAgent.deserialize(result, clazz);
    }

    @Override
    public boolean set(String key, String data) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, data);
        return true;
    }

    @Override
    public boolean set(String key, Object data) {
        String value = JsonAgent.serialize(data);
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, value);
        return true;
    }

    @Override
    public boolean set(String key, String data, int second) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, data, second, TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean set(String key, Object data, int second) {
        String value = JsonAgent.serialize(data);
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, value, second, TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public boolean setNext(String key, Object data, int second) {
        String value = JsonAgent.serialize(data);
        boolean result = redisTemplate.opsForValue().setIfAbsent(key, value);
        redisTemplate.expire(key, second, TimeUnit.SECONDS);
        return result;
    }

    @Override
    public boolean del(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public long nextNumber(String key) {
        return nextNumber(key, 1);
    }

    @Override
    public long nextNumber(String key, int number) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        return valueOperation.increment(key, number);
    }

    @Override
    public boolean mapSet(String mapKey, String key, Object data) {
        String value = JsonAgent.serialize(data);
        HashOperations<String, String, String> map = redisTemplate.opsForHash();
        map.put(mapKey, key, value);
        return true;
    }

    @Override
    public <T> T mapGet(String mapKey, String key, Class<T> clazz) {
        HashOperations<String, String, String> map = redisTemplate.opsForHash();
        String value = map.get(mapKey, key);
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        return JsonAgent.deserialize(value, clazz);
    }

    @Override
    public boolean mapDel(String mapKey, String key) {
        HashOperations<String, String, String> map = redisTemplate.opsForHash();
        return map.delete(mapKey, key) != 0;
    }

    @Override
    public boolean mapExists(String mapKey, String key) {
        HashOperations<String, String, String> map = redisTemplate.opsForHash();
        return map.hasKey(mapKey, key);
    }

    @Override
    public <T> Set<T> zGet(String key, double minScore, double maxScore, Class<T> clazz) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Set<String> resultString = zSetOperations.rangeByScore(key, minScore, maxScore);
        if (ObjectUtils.isEmpty(resultString)) {
            return null;
        }
        Set<T> result = new HashSet<>();
        for (String s : resultString) {
            result.add(JsonAgent.deserialize(s, clazz));
        }
        return result;
    }

    @Override
    public boolean zSet(String key, double score, Object object) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        zSetOperations.add(key, JsonAgent.serialize(object), score);
        return true;
    }

    @Override
    public boolean zDel(String key, Object object) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        zSetOperations.remove(key, object);
        return true;
    }
}
